home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #11 / Amiga Plus CD - 2004 - No. 11.iso / AmiSoft / Dev / misc / temgen.lha / Temgen / tg-0.11 / omani.c < prev    next >
C/C++ Source or Header  |  2002-12-18  |  11KB  |  483 lines

  1. #include "alloc.h"
  2. #include "sysdefs.h"
  3. #include "omani.h"
  4. #include "list.h"
  5.  
  6. #define  DEF_HSIZE     2063   
  7. #define  DEF_FHSIZE    2063   
  8. #define  CHECK( err )  { if (!otab) inittable(); if (!otab) return err; }
  9.  
  10. /* array (list) of objects */
  11. struct array {
  12.     struct list_head list;         /* linked with *.parent fields       */
  13.     struct list_head *cur;         /* current item, indexed with curndx */
  14.     int curndx;                    /* index of *cur item */
  15.     int count;                     /* total items number */  
  16. };
  17.  
  18. /* main object data structure */
  19. struct object {
  20.     struct list_head list;         /* 'otab' hash table link, cannot be 0 */
  21.     struct list_head parent;       /* link to list of siblings, can be 0  */
  22.     int id;                        /* unique id  */       
  23.     char type;                     /* '\0', 'i', 'f', 's', 'a', 'r',
  24.                                       'R' - reference */
  25.     union value {
  26.         struct array *a;       /* for 'a' and 'r' objects           */
  27.         int   i;
  28.         float f;
  29.         char *s;
  30.     } val;
  31. };
  32.  
  33. /* field of 'l'-typed object */
  34. struct ofield {
  35.     struct list_head list;         /* 'ftab' hash table link           */
  36.     struct list_head parent;       /* link to object.val.a->list       */
  37.     int obj, fld;
  38.     struct object *data;
  39. };
  40.  
  41. /* object hash table */
  42. static unsigned hsize = DEF_HSIZE;
  43. static struct list_head *otab = NULL;
  44. static int last_obj = 0;
  45. static int root_obj = 0;
  46. /* field hash table */
  47. static unsigned fhsize = DEF_FHSIZE;
  48. static struct list_head *ftab = NULL;
  49.  
  50. static unsigned hval( int id )
  51. {
  52.     return ((unsigned)id) % hsize;
  53. }
  54.  
  55. static unsigned fhval( int obj, int fld )
  56. {
  57.     return ((obj << 18) | fld) % fhsize;
  58. }
  59.  
  60. int ob_sethsize( unsigned h, unsigned fh )
  61. {
  62.     if (otab || ftab) return -1;
  63.     if ( h ) hsize = h;
  64.     if ( fh ) fhsize = fh;
  65.     return 0;
  66. }
  67.  
  68. static void inittable( void )
  69. {
  70.     int i;
  71.     otab = (struct list_head*)CALLOC( hsize, sizeof(otab[0]));
  72.     if ( otab ) 
  73.         for ( i=0; i<hsize; i++ )
  74.             INIT_LIST_HEAD( otab+i );
  75.     last_obj = 0;
  76.     root_obj = 0;
  77.  
  78.     ftab = (struct list_head*)CALLOC( fhsize, sizeof(ftab[0]));
  79.     if ( ftab ) 
  80.         for ( i=0; i<fhsize; i++ )
  81.             INIT_LIST_HEAD( ftab+i );
  82. }
  83.  
  84. static struct object *create_object( void )
  85. {
  86.     struct object *ob;
  87.     unsigned hv;
  88.  
  89.     CHECK( NULL );
  90.     ob = (struct object*)MALLOC( sizeof(*ob) );
  91.     if ( !ob ) return 0;
  92.     memset( ob, 0, sizeof(*ob) );
  93.     ob->id = ++last_obj;
  94.     hv = hval( ob->id );
  95.     list_add( &ob->list, otab+hv );
  96.     return ob;
  97. }
  98.  
  99. int ob_root( void )
  100. {
  101.     struct object *ob;
  102.     if ( root_obj <= 0 ) {
  103.         ob = create_object();
  104.         root_obj = ob ? ob->id: 0;
  105.     }
  106.     return root_obj;
  107. }
  108.  
  109. static struct object *find_object( int id )
  110. {
  111.     unsigned hv;
  112.     struct list_head *p;
  113.     struct object *ob;
  114.  
  115.     if ( !otab ) return NULL;
  116.     hv = hval( id );
  117.     for ( p=otab[ hv ].next; p != otab + hv; p = p->next ) {
  118.         ob = list_entry( p, struct object, list );
  119.         if ( ob->id == id ) return ob;
  120.     }
  121.  
  122.     return NULL;
  123. }
  124.  
  125.  
  126. static void free_value( struct object* );
  127.  
  128. static void free_object( struct object *ob )
  129. {
  130.     if ( !ob ) return;
  131.     if ( ob->list.next ) list_del( &ob->list );
  132.     if ( ob->parent.next ) list_del( &ob->parent );
  133.     free_value( ob );
  134.     FREE( ob );
  135. }
  136.  
  137. static void free_ofield( struct ofield *f )
  138. {
  139.     if ( f ) {
  140.         if ( f->list.next ) list_del( &f->list );
  141.         if ( f->parent.next ) list_del( &f->parent );
  142.         if ( f->data ) free_object( f->data );
  143.         FREE( f );
  144.     }
  145. }
  146.  
  147. static void free_array( int owner, struct array *a )
  148. {
  149.     if ( !a ) return;
  150.  
  151.     if ( owner ) {   /* 'r' type */
  152.         if ( a->list.next ) {
  153.             while( a->list.next != &a->list ) {
  154.                 struct ofield *f;
  155.                 f = list_entry( a->list.next, struct ofield, parent );
  156.                 free_ofield( f );
  157.             }
  158.         }
  159.     }
  160.     else {       /* 'a' array type */
  161.         if ( a->list.next ) {
  162.             while( a->list.next != &a->list ) {
  163.                 struct object *ob;
  164.                 ob = list_entry( a->list.next, struct object, parent );
  165.                 free_object( ob );
  166.             }
  167.         }
  168.     }
  169.  
  170.     FREE( a );
  171. }
  172.  
  173. static void free_value( struct object *ob )
  174. {
  175.     if ( ob ) {
  176.         switch( ob->type ) {
  177.             case 'a':
  178.                 if ( ob->val.a ) free_array( 0, ob->val.a );
  179.                 break;
  180.             case 'r':
  181.                 if ( ob->val.a ) free_array( ob->id, ob->val.a );
  182.                 break;
  183.             case 's':
  184.                 if ( ob->val.s ) FREE( ob->val.s );
  185.                 break;
  186.         }
  187.  
  188.         ob->type = 0;
  189.     }
  190. }
  191.  
  192. int ob_set( int obj, char type, ... )
  193. {
  194.     va_list ap;
  195.     struct object *ob;
  196.     int i;
  197.     float f;
  198.     char *s;
  199.     ob = find_object( obj );
  200.     if ( !ob ) return -1;
  201.     free_value( ob );
  202.     va_start( ap, type );
  203.     ob->type = type;
  204.     switch( type ) {
  205.         case 'R':
  206.         case 'i':
  207.             i = va_arg( ap, int );
  208.             ob->val.i = i;
  209.             break;
  210.         case 'f':
  211.             f = va_arg( ap, double );
  212.             ob->val.f = f;
  213.             break;
  214.         case 's':
  215.             s = va_arg( ap, char* );
  216.             ob->val.s = STRDUP( s );
  217.             if ( !ob->val.s ) { 
  218.                 ob->type = 0;
  219.                 va_end( ap );
  220.                 return -1;
  221.             }
  222.             break;
  223.         default:
  224.             ob->type = 0;
  225.             va_end( ap );
  226.             return -1;
  227.     }
  228.  
  229.     va_end( ap );
  230.     return 0;
  231. }
  232.  
  233. static int arr_item( struct array *a, int index )
  234. {
  235.     struct object *ob;
  236.  
  237.     if ( !a ) return 0;
  238.     if ( index < 0 || index >= a->count ) return 0;
  239.  
  240.     /* TODO - array item access optim. */
  241.     a->cur = 0;
  242.     if ( !a->cur ) {
  243.         a->cur = a->list.next;
  244.         a->curndx = 0;
  245.     }
  246.  
  247.     if ( index > a->curndx ) {
  248.         while( index > a->curndx ) {
  249.             a->cur = a->cur->next;
  250.             a->curndx++;
  251.         }
  252.     }
  253.     else if ( index < a->curndx ) {
  254.         while( index < a->curndx ) {
  255.             a->cur = a->cur->prev;
  256.             a->curndx--;
  257.         }
  258.     }
  259.  
  260.     if ( index == a->curndx ) {
  261.         ob = list_entry( a->cur, struct object, parent );
  262.         return ob->id;
  263.     }
  264.  
  265.     return 0;
  266. }
  267.  
  268. static int rec_item( struct array *a, int index )
  269. {
  270.     struct ofield *f;
  271.  
  272.     if ( !a ) return 0;
  273.     if ( index < 0 || index >= a->count ) return 0;
  274.  
  275.     if ( !a->cur ) {
  276.         a->cur = a->list.next;
  277.         a->curndx = 0;
  278.     }
  279.  
  280.     if ( index > a->curndx ) {
  281.         while( index > a->curndx ) {
  282.             a->cur = a->cur->next;
  283.             a->curndx++;
  284.         }
  285.     }
  286.     else if ( index < a->curndx ) {
  287.         while( index < a->curndx ) {
  288.             a->cur = a->cur->prev;
  289.             a->curndx--;
  290.         }
  291.     }
  292.  
  293.     if ( index == a->curndx ) {
  294.         f = list_entry( a->cur, struct ofield, parent );
  295.         return f->fld;
  296.     }
  297.  
  298.     return 0;
  299. }
  300.  
  301. static int arr_append( struct array *a )
  302. {
  303.     struct object *ob;
  304.  
  305.     if ( !a ) return -1;
  306.     ob = create_object();
  307.     if ( !ob ) return -1;
  308.     list_add( &ob->parent, a->list.prev );
  309.     a->cur = a->list.prev;
  310.     a->curndx = a->count++;
  311.     /* TODO  */
  312.     a->cur = 0;
  313.     a->curndx = 0;
  314.     return 0;
  315. }
  316.  
  317. int ob_item( int obj, int index )
  318. {
  319.     struct object *ob;
  320.  
  321.     ob = find_object( obj );
  322.     if ( !ob ) return 0; 
  323.  
  324.     if ( ob->type != 'a' ) {
  325.         free_value( ob );
  326.         ob->type = 'a';
  327.         ob->val.a = (struct array*)MALLOC( sizeof(*ob->val.a) );
  328.         if ( !ob->val.a ) {
  329.             ob->type = 0;
  330.             return 0;
  331.         } 
  332.         memset( ob->val.a, 0, sizeof( *ob->val.a ));
  333.         INIT_LIST_HEAD( &ob->val.a->list );
  334.     }
  335.  
  336.     if ( index < 0 ) return 0;
  337.     while( index >= ob->val.a->count ) 
  338.         if ( arr_append( ob->val.a )) return 0;
  339.  
  340.     return arr_item( ob->val.a, index );
  341. }
  342.  
  343. char *ob_gets( int obj )
  344. {
  345.     struct object *ob;
  346.  
  347.     ob = find_object( obj );
  348.     if ( !ob ) return NULL;
  349.  
  350.     return (ob->type == 's') ? ob->val.s: NULL;
  351. }
  352.  
  353. int ob_geti( int obj )
  354. {
  355.     struct object *ob;
  356.  
  357.     ob = find_object( obj );
  358.     if ( !ob ) return 0;
  359.  
  360.     return ob->val.i;
  361. }
  362.  
  363. float ob_getf( int obj )
  364. {
  365.     struct object *ob;
  366.  
  367.     ob = find_object( obj );
  368.     if ( !ob ) return 0;
  369.  
  370.     return ob->val.f;
  371. }
  372.  
  373. char ob_type( int obj )
  374. {
  375.     struct object *ob;
  376.  
  377.     ob = find_object( obj );
  378.     if ( !ob ) return 0;
  379.  
  380.     return ob->type;
  381. }
  382.  
  383. int ob_count( int obj )
  384. {
  385.     struct object *ob;
  386.  
  387.     ob = find_object( obj );
  388.     if ( !ob ) return 0;
  389.  
  390.     return (ob->type=='a' || ob->type=='r') ? ob->val.a->count: 0;
  391. }
  392.  
  393. static struct ofield *create_field( int obj, int fld, unsigned hv )
  394. {
  395.     struct object *ob;
  396.     struct ofield *f;
  397.     
  398.     ob = find_object( obj );
  399.     if ( !ob ) return NULL;
  400.     
  401.     if ( ob->type != 'r' ) {
  402.         free_value( ob );
  403.         ob->type = 'r';
  404.         ob->val.a = (struct array*)MALLOC( sizeof(*ob->val.a) );
  405.         if ( !ob->val.a ) {
  406.             ob->type = 0;
  407.             return NULL;
  408.         } 
  409.         memset( ob->val.a, 0, sizeof( *ob->val.a ));
  410.         INIT_LIST_HEAD( &ob->val.a->list );
  411.     }
  412.     
  413.     f = (struct ofield*)MALLOC( sizeof(*f) );
  414.     if ( !f ) return NULL;
  415.     
  416.     memset( f, 0, sizeof(*f) );
  417.     f->obj = obj;
  418.     f->fld = fld;
  419.     f->data = create_object();
  420.     if ( !f->data ) {
  421.         FREE( f );
  422.         return NULL;
  423.     }
  424.     
  425.     list_add( &f->list, ftab+hv );
  426.     list_add( &f->parent, &ob->val.a->list );
  427.    /***** TODO  ***/
  428.     ob->val.a->cur = ob->val.a->list.prev;
  429.     ob->val.a->curndx = ob->val.a->count++; 
  430.  /* ob->val.a->cur = 0;
  431.     ob->val.a->curndx = 0;        */
  432.     return f;
  433. }
  434.  
  435. int ob_field( int obj, int fld )
  436. {
  437.     unsigned hv;
  438.     struct list_head *p;
  439.     struct ofield *f = NULL;
  440.     
  441.     if ( !( otab && ftab ) ) return 0;
  442.     
  443.     hv = fhval( obj, fld );
  444.     for ( p=ftab[ hv ].next; p != ftab+hv; p = p->next ) {
  445.         f = list_entry( p, struct ofield, list );
  446.         if ( f->obj==obj && f->fld==fld ) break;
  447.         f = NULL;
  448.     }
  449.     
  450.     if ( !f ) f = create_field( obj, fld, hv );
  451.     
  452.     return f ? f->data->id: 0;
  453. }
  454.  
  455. int ob_defined( int obj, int fld )
  456. {
  457.     unsigned hv;
  458.     struct list_head *p;
  459.     struct ofield *f;
  460.     
  461.     if ( !( otab && ftab ) ) return 0;
  462.     
  463.     hv = fhval( obj, fld );
  464.     for ( p=ftab[ hv ].next; p != ftab+hv; p = p->next ) {
  465.         f = list_entry( p, struct ofield, list );
  466.         if ( f->obj==obj && f->fld==fld ) return 1;
  467.     }
  468.     
  469.     return 0;
  470. }
  471.  
  472. int ob_fieldname( int obj, int index )
  473. {
  474.     struct object *ob;
  475.     
  476.     ob = find_object( obj );
  477.     if ( !ob ) return 0;
  478.  
  479.     if ( ob->type != 'r' ) return 0; 
  480.     return rec_item( ob->val.a, index );
  481. }
  482.  
  483.